package com.miyu.common.utils.aop;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.date.DateUtil;

import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONReader;
import com.miyu.common.pojo.system.SysApiLog;
import com.miyu.common.utils.commonUtils.IpUtils;
import com.miyu.common.utils.commonUtils.Rediscache;
import com.miyu.common.utils.filter.exception.CosException;
import com.miyu.common.utils.taskJob.RedisTaskCahe;
import com.miyu.common.utils.web.PropertiesUtil;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toList;


/**
 * api调用日志信息记录
 *
 * @author longm
 * @date 2022/10/08
 */
public class ApiLogInfo {
    static ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(15, new BasicThreadFactory.Builder()
            .namingPattern("api-log-%d").daemon(true).build());
    public static void ApiLogCache(ProceedingJoinPoint joinPoint, Object proceed, Date beginTime, Date endTime){
//        获取RequestAttributes
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        //从获取RequestAttributes中获取HttpServletRequest的信息
        HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
        //如果要获取Session信息的话，可以这样写：
        HttpSession session = (HttpSession) requestAttributes.resolveReference(RequestAttributes.REFERENCE_SESSION);
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        // 请求的方法参数值
        Object[] args = joinPoint.getArgs();
        // 请求的方法参数名称
        LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
        String[] paramNames = u.getParameterNames(method);
        String params = "";
        if (args != null && paramNames != null) {
            for (int i = 0; i < args.length; i++) {
//                System.out.println(i+" paramNames[i]="+paramNames[i]+",args[i]="+args[i]);
                params += args[i];
            }
        }
        // 设置IP地址
        String ip = IpUtils.getIpAddr(request);
        // 请求的方法名
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = signature.getName();
        //POST/GET
        String type = request.getMethod();
        //查询返回值
        //返回结果
        //System.out.println("proceed=" + proceed.toString());
        SysApiLog sysApiLog = new SysApiLog();
        JSONObject data = new JSONObject();
        data.put("code","200");
        data.put("msg","OK");
        data.put("data",proceed);
        JSONObject log = new JSONObject();
        // 判断是否登录
        if(StpUtil.isLogin()){
            //登录账户
            log.put("operateAccount",StpUtil.getLoginId());
            //登录类型
            log.put("loginType",StpUtil.getLoginDevice());
        }

        sysApiLog.setOperateIp(ip);
        sysApiLog.setOperateParam(params);
        sysApiLog.setOperateApi(methodName);
        sysApiLog.setOperateType(type);
        sysApiLog.setBeginTime(beginTime);
        sysApiLog.setEndTime(endTime);
        sysApiLog.setClassName(className);
        sysApiLog.setModuleCode(PropertiesUtil.getProperty("spring.application.name"));
        sysApiLog.setCode("200");
        /** 地址归属*/
       sysApiLog.setIpAddress(IpUtils.IpAddress(IpUtils.search(ip),4));
       /** 校验api日志写入是否记录*/

        JSONObject logSet =  JSONObject.parseObject(String.valueOf(Rediscache.get("system:sysLog:sysLogSet"))) ;
        List<String> methodSet = new ArrayList<String>();
        List<String> packName = new ArrayList<String>();
        if(logSet!=null&&logSet.containsKey("methodName")){
            methodSet =  logSet.getList("methodName",String.class);
        }
        if(logSet!=null&&logSet.containsKey("packName")){
            packName =   logSet.getList("packName",String.class);
        }
        //判断所在包位置 暂时只存储system 程序数据
        if(!methodSet.contains(methodName)){
            executorService.submit(new RedisTaskCahe(1,1,"log:api-log",JSONObject.parse(JSONObject.toJSONString(sysApiLog), JSONReader.Feature.IgnoreSetNullValue) ));
        }
    }
}
